<template>
  <div ref="chartBox" class="chart_box">
    <div ref="chartRef" class="chart wh-full"></div>
    <slot name="custom" :chart="chart"></slot>
  </div>
</template>

<script setup>
import * as echarts from 'echarts'
import { CanvasRenderer, SVGRenderer } from 'echarts/renderers'

const props = defineProps({
  chartOptions: {
    type: Object || Function,
  },
  rendererProps: {
    type: String,
    default: 'canvas',
  },
  notMerge: {
    type: Boolean,
    default: false,
  },
})
const emit = defineEmits(['targetEvent', 'chartClick'])

echarts.use([SVGRenderer, CanvasRenderer])

const chartRef = useTemplateRef('chartRef')
const chartBox = useTemplateRef('chartBox')

const chartClear = (target) => {
  target && target?.clear?.()
  target && target?.dispose?.()
}
const chart = shallowRef(null)
const options = computed(() => {
  return Object.assign(
    {},
    Object.prototype.toString.call(props.chartOptions) === '[object Object]' ? props.chartOptions : props?.chartOptions?.(),
  )
})

const panelXChange = inject('panelXChange', {})
const panelYChange = inject('panelYChange', {})
watch(
  () => [panelXChange?.exposed?.target, panelYChange?.exposed?.target],
  (val) => {
    let timer
    const fn = () => {
      chart.value?.resize?.()
      timer && cancelAnimationFrame(timer)
      if (chart.value) {
        timer = requestAnimationFrame(fn)
      }
    }

    if (chart.value) {
      timer = requestAnimationFrame(fn)
      setTimeout(() => {
        timer && cancelAnimationFrame(timer)
      }, 500)
    }
  },
  {
    deep: true,
  },
)

let ob = null

const initChart = () => {
  echarts.registerTheme('customTheme', {
    tooltip: {
      className: 'custom-tooltip',
      appendTo: 'body',
    },
  })
  nextTick(() => {
    if (chart.value == null) {
      chart.value = echarts.init(chartRef.value, 'customTheme', {
        renderer: props.rendererProps,
        locale: 'ZH', // 从 `5.0.0` 开始支持
      })
    }
    chart.value.setOption(options.value, { notMerge: props.notMerge })

    emit('targetEvent', chart.value)
    chart.value.off('click')
    chart.value.on('click', function (param) {
      emit('chartClick', param, this)
    })
    window.addEventListener(
      'resize',
      () => {
        chart.value?.resize?.()
      },
      // false
      { passive: true },
    )
    setTimeout(() => {
      // chart.value?.resize?.()
      ob = new ResizeObserver((entries) => {
        chart.value?.resize?.()
      })
      ob.observe(chartBox.value)
    }, 20)
  })
}

onBeforeUnmount(() => {
  chart.value?.off?.('click')
  window.removeEventListener('resize', () => chart.value.resize(), false)
  chartClear(chart.value)
  ob?.disconnect?.()
})
watch(
  () => props.chartOptions,
  (val) => {
    nextTick(() => {
      chart.value?.resize?.()
    })
    initChart()
  },
  { deep: true, immediate: true },
)
defineExpose({ chart })
</script>

<style lang="scss" scoped>
.chart_box {
  @apply w-full h-full relative;

  .chart {
    @apply absolute w-full h-full top-0 left-0 z-2;
  }
}
.custom-tooltip {
  z-index: 999999999;
}
</style>
